model button: Complete the CSS node conversion
authorMatthias Clasen <mclasen@redhat.com>
Tue, 3 Nov 2015 17:20:53 +0000 (12:20 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 3 Nov 2015 17:20:53 +0000 (12:20 -0500)
There was still style context saving in the draw function,
and the CSS node was not always properly updated and positioned.
Fix these things, and use the same CSS node for the arrow
drawing as well.

gtk/gtkmodelbutton.c

index d3c791647d9a6ef0fa18bd21292d0815e64aeee5..e65cc80418c974a16c9e9c241d3750403356e600 100644 (file)
@@ -143,24 +143,70 @@ enum
 
 static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
 
+static gboolean
+indicator_is_left (GtkWidget *widget)
+{
+  GtkModelButton *button = GTK_MODEL_BUTTON (widget);
+
+  return ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL && !button->inverted) ||
+          (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR && button->inverted));
+}
+
 static void
 gtk_model_button_update_state (GtkModelButton *button)
 {
   GtkStateFlags state;
 
-  if (button->role == GTK_BUTTON_ROLE_NORMAL)
-    return;
-
   state = gtk_widget_get_state_flags (GTK_WIDGET (button));
 
-  state &= ~GTK_STATE_FLAG_CHECKED;
+  if (button->role == GTK_BUTTON_ROLE_CHECK ||
+      button->role == GTK_BUTTON_ROLE_RADIO)
+    {
+      state &= ~GTK_STATE_FLAG_CHECKED;
 
-  if (button->active && !button->menu_name)
-    state |= GTK_STATE_FLAG_CHECKED;
+      if (button->active && !button->menu_name)
+        state |= GTK_STATE_FLAG_CHECKED;
+    }
+
+  if (button->menu_name)
+    {
+      state = state & ~(GTK_STATE_FLAG_DIR_LTR|GTK_STATE_FLAG_DIR_RTL);
+      if (indicator_is_left (GTK_WIDGET (button)))
+        state = state | GTK_STATE_FLAG_DIR_RTL;
+      else
+        state = state | GTK_STATE_FLAG_DIR_LTR;
+    }
 
   gtk_css_node_set_state (button->indicator_node, state);
 }
 
+static void
+update_node_ordering (GtkModelButton *button)
+{
+  GtkCssNode *widget_node, *node;
+
+  widget_node = gtk_widget_get_css_node (GTK_WIDGET (button));
+
+  if (indicator_is_left (GTK_WIDGET (button)))
+    {
+      gtk_css_node_add_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_LEFT));
+      gtk_css_node_remove_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_RIGHT));
+
+      node = gtk_css_node_get_first_child (widget_node);
+      if (node != button->indicator_node)
+        gtk_css_node_insert_before (widget_node, button->indicator_node, node);
+    }
+  else
+    {
+      gtk_css_node_remove_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_LEFT));
+      gtk_css_node_add_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_RIGHT));
+
+      node = gtk_css_node_get_last_child (widget_node);
+      if (node != button->indicator_node)
+        gtk_css_node_insert_after (widget_node, button->indicator_node, node);
+    }
+}
+
 static void
 gtk_model_button_state_flags_changed (GtkWidget     *widget,
                                       GtkStateFlags  previous_flags)
@@ -169,26 +215,40 @@ gtk_model_button_state_flags_changed (GtkWidget     *widget,
 }
 
 static void
-gtk_model_button_set_role (GtkModelButton *button,
-                           GtkButtonRole   role)
+gtk_model_button_direction_changed (GtkWidget        *widget,
+                                    GtkTextDirection  previous_dir)
+{
+  GtkModelButton *button = GTK_MODEL_BUTTON (widget);
+
+  gtk_model_button_update_state (button);
+  update_node_ordering (button);
+
+  GTK_WIDGET_CLASS (gtk_model_button_parent_class)->direction_changed (widget, previous_dir);
+}
+
+static void
+update_node_name (GtkModelButton *button)
 {
   AtkObject *accessible;
   AtkRole a11y_role;
   const gchar *name;
   gboolean visible;
 
-  if (role == button->role)
-    return;
-
-  button->role = role;
-
   accessible = gtk_widget_get_accessible (GTK_WIDGET (button));
-  switch (role)
+  switch (button->role)
     {
     case GTK_BUTTON_ROLE_NORMAL:
       a11y_role = ATK_ROLE_PUSH_BUTTON;
-      name = I_("check");
-      visible = FALSE;
+      if (button->menu_name)
+        {
+          name = I_("arrow");
+          visible = TRUE;
+        }
+      else
+        {
+          name = I_("check");
+          visible = FALSE;
+        }
       break;
 
     case GTK_BUTTON_ROLE_CHECK:
@@ -210,6 +270,18 @@ gtk_model_button_set_role (GtkModelButton *button,
   atk_object_set_role (accessible, a11y_role);
   gtk_css_node_set_name (button->indicator_node, name);
   gtk_css_node_set_visible (button->indicator_node, visible);
+}
+
+static void
+gtk_model_button_set_role (GtkModelButton *button,
+                           GtkButtonRole   role)
+{
+  if (role == button->role)
+    return;
+
+  button->role = role;
+
+  update_node_name (button);
 
   gtk_model_button_update_state (button);
   gtk_widget_queue_draw (GTK_WIDGET (button));
@@ -266,7 +338,15 @@ gtk_model_button_set_menu_name (GtkModelButton *button,
 {
   g_free (button->menu_name);
   button->menu_name = g_strdup (menu_name);
+
+  update_node_name (button);
   gtk_model_button_update_state (button);
+
+  if (menu_name)
+    gtk_css_node_add_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_EXPANDER));
+  else
+    gtk_css_node_remove_class (button->indicator_node, g_quark_from_static_string (GTK_STYLE_CLASS_EXPANDER));
+
   gtk_widget_queue_resize (GTK_WIDGET (button));
   g_object_notify_by_pspec (G_OBJECT (button), properties[PROP_MENU_NAME]);
 }
@@ -279,6 +359,8 @@ gtk_model_button_set_inverted (GtkModelButton *button,
     return;
 
   button->inverted = inverted;
+  gtk_model_button_update_state (button);
+  update_node_ordering (button);
   gtk_widget_queue_resize (GTK_WIDGET (button));
   g_object_notify_by_pspec (G_OBJECT (button), properties[PROP_INVERTED]);
 }
@@ -647,16 +729,6 @@ gtk_model_button_get_preferred_height (GtkWidget *widget,
                                                                 NULL, NULL);
 }
 
-static gboolean
-indicator_is_left (GtkWidget *widget)
-{
-  GtkModelButton *button = GTK_MODEL_BUTTON (widget);
-
-  return ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL && !button->inverted) ||
-          (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR && button->inverted));
-   
-}
-
 static void
 gtk_model_button_size_allocate (GtkWidget     *widget,
                                 GtkAllocation *allocation)
@@ -764,18 +836,7 @@ gtk_model_button_draw (GtkWidget *widget,
 
   if (model_button->menu_name)
     {
-      GtkStateFlags state;
-
-      gtk_style_context_save_named (context, "arrow");
-      state = gtk_style_context_get_state (context);
-      state = state & ~(GTK_STATE_FLAG_DIR_LTR|GTK_STATE_FLAG_DIR_RTL);
-      if (indicator_is_left (widget))
-        state = state | GTK_STATE_FLAG_DIR_RTL;
-      else
-        state = state | GTK_STATE_FLAG_DIR_LTR;
-
-      gtk_style_context_set_state (context, state);
-      gtk_style_context_add_class (context, GTK_STYLE_CLASS_EXPANDER);
+      gtk_style_context_save_to_node (context, model_button->indicator_node);
       gtk_render_expander (context, cr, x, y, indicator_size, indicator_size);
       gtk_style_context_restore (context);
     }
@@ -863,6 +924,7 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
   widget_class->draw = gtk_model_button_draw;
   widget_class->destroy = gtk_model_button_destroy;
   widget_class->state_flags_changed = gtk_model_button_state_flags_changed;
+  widget_class->direction_changed = gtk_model_button_direction_changed;
 
   button_class->clicked = gtk_model_button_clicked;